home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / mh / mh-6.8 / zotnet / mts / client.c next >
Encoding:
C/C++ Source or Header  |  1992-12-14  |  8.5 KB  |  419 lines

  1. /* client.c - connect to a server */
  2. #ifndef    lint
  3. static char ident[] = "@(#)$Id: client.c,v 1.19 1992/12/15 00:20:22 jromine Exp $";
  4. #endif    /* lint */
  5.  
  6. #if    defined(SYS5) && defined(AUX)
  7. #define    u_short    ushort
  8. #define u_long  ulong
  9. #endif
  10.  
  11.  
  12. #if    defined(BSD42) || defined(SOCKETS)
  13. #include "../h/strings.h"
  14. #include <stdio.h>
  15. #include "mts.h"
  16. #include <errno.h>
  17. #include <sys/types.h>
  18. #include <sys/socket.h>
  19. #include <netinet/in.h>
  20. #include <netdb.h>
  21. #ifndef    hpux
  22. #include <arpa/inet.h>
  23. #endif
  24.  
  25. #ifdef    HESIOD
  26. #include <hesiod.h>
  27. #endif
  28.  
  29. #ifdef KPOP
  30. #include <krb.h>
  31. #include <ctype.h>
  32.  
  33. static CREDENTIALS cred;
  34. static MSG_DAT msg_data;
  35. static KTEXT ticket = (KTEXT)NULL;
  36. static Key_schedule schedule;
  37. #endif    /* KPOP */
  38.  
  39. #define    NOTOK    (-1)
  40. #define    OK    0
  41. #define    DONE    1
  42.  
  43. #define    TRUE    1
  44. #define    FALSE    0
  45.  
  46. #define    OOPS1    (-2)
  47. #define    OOPS2    (-3)
  48.  
  49. #define    MAXARGS        1000
  50. #define    MAXNETS        5
  51. #define    MAXHOSTS    25
  52.  
  53. /*   */
  54.  
  55. extern int errno;
  56. extern int  sys_nerr;
  57. extern char *sys_errlist[];
  58.  
  59.  
  60. struct addrent {
  61.     int     a_addrtype;        /* assumes AF_INET for inet_netof () */
  62.  
  63.     union {
  64.     int    un_net;
  65.     char    un_addr[14];
  66.     } un;
  67. #define    a_net    un.un_net
  68. #define    a_addr    un.un_addr
  69. };
  70.  
  71. static struct addrent *ne, *nz;
  72. static struct addrent nets[MAXNETS];
  73.  
  74. static struct addrent *he, *hz;
  75. static struct addrent hosts[MAXHOSTS];
  76.  
  77. #ifdef KPOP
  78. char krb_realm[REALM_SZ];
  79. char *PrincipalHostname();
  80. static char *kservice;        /* "pop" if using kpop */
  81. #endif /* KPOP */
  82.  
  83. #ifdef __STDC__
  84. static int rcaux (struct servent *, struct hostent *, int, char *);
  85. static int getport (int, int, char *);
  86. static int inet (struct hostent *, int);
  87. #else
  88. static int rcaux (), getport (), inet ();
  89. #endif
  90.  
  91. static int brkany ();
  92. static char *getcpy (), **copyip (), **brkstring ();
  93.  
  94. /*   */
  95.  
  96. int    client (args, protocol, service, rproto, response)
  97. char   *args,
  98.        *protocol,
  99.        *service,    /* "pop" or "pop/kpop" */
  100.        *response;
  101. int    rproto;
  102. {
  103.     int     sd;
  104.     register char **ap;
  105.     char   *arguments[MAXARGS];
  106.     register struct hostent *hp;
  107. #ifndef    BIND
  108.     register struct netent *np;
  109. #endif
  110.     register struct servent *sp;
  111. #ifdef    KPOP
  112.     char *cp;
  113.  
  114.     if (cp = index (kservice = service, '/')) {    /* "pop/kpop" */
  115.     *cp++ = '\0';        /* kservice = "pop" */
  116.     service = cp;        /* service  = "kpop" */
  117.     }
  118.     else
  119.     kservice = NULL;    /* not using KERBEROS */
  120. #endif    /* KPOP */
  121.     
  122.  
  123.     if ((sp = getservbyname (service, protocol)) == NULL) {
  124. #ifdef    HESIOD
  125.     if ((sp = hes_getservbyname (service, protocol)) == NULL) {
  126.         (void) sprintf (response, "%s/%s: unknown service",
  127.             protocol, service);
  128.         return NOTOK;
  129.     }
  130. #else
  131.     (void) sprintf (response, "%s/%s: unknown service", protocol, service);
  132.     return NOTOK;
  133. #endif
  134.     }
  135.  
  136.     ap = arguments;
  137.     if (args != NULL && *args != 0)
  138.     ap = copyip (brkstring (getcpy (args), " ", "\n"), ap);
  139.     else
  140.     if (servers != NULL && *servers != 0)
  141.         ap = copyip (brkstring (getcpy (servers), " ", "\n"), ap);
  142.     if (ap == arguments) {
  143.     *ap++ = getcpy ("localhost");
  144.     *ap = NULL;
  145.     }
  146.  
  147.     nz = (ne = nets) + sizeof nets / sizeof nets[0];
  148.     hz = (he = hosts) + sizeof hosts / sizeof hosts[0];
  149.  
  150.     for (ap = arguments; *ap; ap++) {
  151.     if (**ap == '\01') {
  152. #ifndef    BIND
  153.         if (np = getnetbyname (*ap + 1)) {
  154.         sethostent (1);
  155.         while (hp = gethostent ())
  156.             if (np -> n_addrtype == hp -> h_addrtype
  157.                 && inet (hp, np -> n_net)) {
  158.             switch (sd = rcaux (sp, hp, rproto, response)) {
  159.                 case NOTOK: 
  160.                 continue;
  161.                 case OOPS1: 
  162.                 break;
  163.                 case OOPS2: 
  164.                 return NOTOK;
  165.  
  166.                 default: 
  167.                 return sd;
  168.             }
  169.             break;
  170.             }
  171.         }
  172. #endif
  173.         continue;
  174.     }
  175.  
  176.     if (hp = gethostbyname (*ap)) {
  177.         switch (sd = rcaux (sp, hp, rproto, response)) {
  178.         case NOTOK: 
  179.         case OOPS1: 
  180.             break;
  181.         case OOPS2: 
  182.             return NOTOK;
  183.  
  184.         default: 
  185.             return sd;
  186.         }
  187.         continue;
  188.     }
  189.     }
  190.  
  191.     (void) strcpy (response, "no servers available");
  192.     return NOTOK;
  193. }
  194.  
  195. /*   */
  196.  
  197. static int  rcaux (sp, hp, rproto, response)
  198. register struct servent *sp;
  199. register struct hostent *hp;
  200. int    rproto;
  201. register char *response;
  202. {
  203.     int     sd;
  204.     struct in_addr  in;
  205.     register struct addrent *ap;
  206.     struct sockaddr_in  in_socket;
  207.     register struct sockaddr_in *isock = &in_socket;
  208. #ifdef KPOP
  209.     int rem;
  210. #endif    /* KPOP */
  211.  
  212.     for (ap = nets; ap < ne; ap++)
  213.     if (ap -> a_addrtype == hp -> h_addrtype && inet (hp, ap -> a_net))
  214.         return NOTOK;
  215.  
  216.     for (ap = hosts; ap < he; ap++)
  217.     if (ap -> a_addrtype == hp -> h_addrtype
  218.         && bcmp (ap -> a_addr, hp -> h_addr, hp -> h_length) == 0)
  219.         return NOTOK;
  220.  
  221.     if ((sd = getport (rproto, hp -> h_addrtype, response)) == NOTOK)
  222.     return OOPS2;
  223.  
  224.     bzero ((char *) isock, sizeof *isock);
  225.     isock -> sin_family = hp -> h_addrtype;
  226.     isock -> sin_port = sp -> s_port;
  227.     bcopy (hp -> h_addr, (char *) &isock -> sin_addr, hp -> h_length);
  228.  
  229.     if (connect (sd, (struct sockaddr *) isock, sizeof *isock) == NOTOK)
  230.     switch (errno) {
  231.         case ENETDOWN: 
  232.         case ENETUNREACH: 
  233.         (void) close (sd);
  234.         if (ne < nz) {
  235.             ne -> a_addrtype = hp -> h_addrtype;
  236.             bcopy (hp -> h_addr, (char *) &in, sizeof in);
  237.             ne -> a_net = inet_netof (in);
  238.             ne++;
  239.         }
  240.         return OOPS1;
  241.  
  242.         case ETIMEDOUT: 
  243.         case ECONNREFUSED: 
  244.         default: 
  245.         (void) close (sd);
  246.         if (he < hz) {
  247.             he -> a_addrtype = hp -> h_addrtype;
  248.             bcopy (hp -> h_addr, he -> a_addr, hp -> h_length);
  249.             he++;
  250.         }
  251.         return NOTOK;
  252.     }
  253.  
  254. #ifdef KPOP
  255.     if (kservice) {    /* "pop" */
  256.     ticket = (KTEXT)malloc( sizeof(KTEXT_ST) );
  257.     rem = krb_sendauth(0L, sd, ticket, kservice, hp->h_name,
  258.                (char *) krb_realmofhost(hp->h_name),
  259.                (unsigned long)0, &msg_data, &cred, schedule,
  260.                (struct sockaddr_in *)NULL,
  261.                (struct sockaddr_in *)NULL,
  262.                "KPOPV0.1");
  263.     if (rem != KSUCCESS) {
  264.         close(sd);
  265.         (void) strcpy(response, "Post office refused connection: ");
  266.         (void) strcat(response, krb_err_txt[rem]);
  267.         return OOPS2;
  268.     }
  269.     }
  270. #endif    /* KPOP */
  271.  
  272.     return sd;
  273. }
  274.  
  275. /*   */
  276.  
  277. static int getport (rproto, addrtype, response)
  278. int    rproto,
  279.     addrtype;
  280. register char *response;
  281. {
  282.     int     sd,
  283.             port;
  284.     struct sockaddr_in  in_socket,
  285.                        *isock = &in_socket;
  286.  
  287.     if (rproto && addrtype != AF_INET) {
  288.     (void) sprintf (response, "reserved ports not supported for af=%d",
  289.         addrtype);
  290.     errno = ENOPROTOOPT;
  291.     return NOTOK;
  292.     }
  293.  
  294.     if ((sd = socket (AF_INET, SOCK_STREAM, 0)) == NOTOK) {
  295.     (void) sprintf (response, "unable to create socket: %s",
  296.         errno > 0 && errno < sys_nerr ? sys_errlist[errno]
  297.         : "unknown error");
  298.     return NOTOK;
  299.     }
  300. #ifdef KPOP
  301.     if (kservice)    /* "pop" */
  302.     return(sd);
  303. #endif    /* KPOP */
  304.     if (!rproto)
  305.     return sd;
  306.  
  307.     bzero ((char *) isock, sizeof *isock);
  308.     isock -> sin_family = addrtype;
  309.     for (port = IPPORT_RESERVED - 1;;) {
  310.     isock -> sin_port = htons ((u_short) port);
  311.     if (bind (sd, (struct sockaddr *) isock, sizeof *isock) != NOTOK)
  312.         return sd;
  313.  
  314.     switch (errno) {
  315.         case EADDRINUSE: 
  316.         case EADDRNOTAVAIL: 
  317.         if (--port <= IPPORT_RESERVED / 2) {
  318.             (void) strcpy (response, "ports available");
  319.             return NOTOK;
  320.         }
  321.         break;
  322.  
  323.         default: 
  324.         (void) sprintf (response, "unable to bind socket: %s",
  325.             errno > 0 && errno < sys_nerr ? sys_errlist[errno]
  326.             : "unknown error");
  327.         return NOTOK;
  328.     }
  329.     }
  330. }
  331.  
  332. /*   */
  333.  
  334. static int  inet (hp, net)
  335. register struct hostent *hp;
  336. int    net;
  337. {
  338.     struct in_addr  in;
  339.  
  340.     bcopy (hp -> h_addr, (char *) &in, sizeof in);
  341.     return (inet_netof (in) == net);
  342. }
  343.  
  344. /*   */
  345.  
  346. /* static copies of three MH subroutines... (sigh) */
  347.  
  348. static char *broken[MAXARGS + 1];
  349.  
  350.  
  351. static char **brkstring (strg, brksep, brkterm)
  352. register char  *strg;
  353. register char  *brksep,
  354.                *brkterm;
  355. {
  356.     register int    bi;
  357.     register char   c,
  358.                    *sp;
  359.  
  360.     sp = strg;
  361.  
  362.     for (bi = 0; bi < MAXARGS; bi++) {
  363.     while (brkany (c = *sp, brksep))
  364.         *sp++ = 0;
  365.     if (!c || brkany (c, brkterm)) {
  366.         *sp = 0;
  367.         broken[bi] = 0;
  368.         return broken;
  369.     }
  370.  
  371.     broken[bi] = sp;
  372.     while ((c = *++sp) && !brkany (c, brksep) && !brkany (c, brkterm))
  373.         continue;
  374.     }
  375.     broken[MAXARGS] = 0;
  376.  
  377.     return broken;
  378. }
  379.  
  380.  
  381. static  brkany (chr, strg)
  382. register char   chr,
  383.                *strg;
  384. {
  385.     register char  *sp;
  386.  
  387.     if (strg)
  388.     for (sp = strg; *sp; sp++)
  389.         if (chr == *sp)
  390.         return 1;
  391.     return 0;
  392. }
  393.  
  394.  
  395. static char **copyip (p, q)
  396. register char **p,
  397.               **q;
  398. {
  399.     while (*p)
  400.     *q++ = *p++;
  401.     *q = 0;
  402.  
  403.     return q;
  404. }
  405.  
  406.  
  407. static char *getcpy (str)
  408. register char  *str;
  409. {
  410.     register char  *cp;
  411.  
  412.     if ((cp = malloc ((unsigned) (strlen (str) + 1))) == NULL)
  413.     return NULL;
  414.  
  415.     (void) strcpy (cp, str);
  416.     return cp;
  417. }
  418. #endif    /* BSD42 or SOCKETS */
  419.